﻿using Nop.Core;
using Nop.Core.Caching;
using Nop.Core.Data;
using Nop.Core.Domain.Security;
using Nop.Core.Domain.Stores;
using Nop.Plugin.Widgets.Ribbon.Domain;
using Nop.Services.Events;
using Nop.Services.Security;
using Nop.Services.Stores;
using System.Linq;
using System;
using System.Collections.Generic;

namespace Nop.Plugin.Widgets.Ribbon.Services
{
    /// <summary>
    /// Extended Customer service
    /// </summary>
    public partial class RibbonService : IRibbonService
    {

        #region Constants
        /// <summary>
        /// Key for caching
        /// </summary>
        /// <remarks>
        /// {0} : page ID
        /// </remarks>
        private const string CAROUSELS_BY_ID_KEY = "Nop.ribbon.id-{0}";
        /// <summary>
        /// Key pattern to clear cache
        /// </summary>
        private const string CAROUSELS_PATTERN_KEY = "Nop.ribbon.";
      
        #endregion

        #region Fields
        private readonly IRepository<RibbonObject> _ribbonRepository;
        private readonly IRepository<RibbonProduct> _ribbonProductRepository;
        private readonly IEventPublisher _eventPublisher;
        private readonly ICacheManager _cacheManager;

         #endregion

        #region Ctor

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="cacheManager">Cache manager</param>
        /// <param name="ribbonRepository">Ribbon repository</param>
        /// <param name="eventPublisher">Event publisher</param>
        public RibbonService(ICacheManager cacheManager,
            IRepository<RibbonObject> ribbonRepository,
            IRepository<RibbonProduct> ribbonProductRepository,
            IEventPublisher eventPublisher)
        {
            this._cacheManager = cacheManager;
            this._ribbonRepository = ribbonRepository;
            this._ribbonProductRepository = ribbonProductRepository;
            this._eventPublisher = eventPublisher;
        }

        #endregion

        #region Methods

        /// <summary>
        /// Delete ribbon
        /// </summary>
        /// <param name="ribbon">Ribbon</param>
        public virtual void DeleteRibbon(RibbonObject ribbon)
        {
            if (ribbon == null)
                throw new ArgumentNullException("ribbon");

            _ribbonRepository.Delete(ribbon);

            //event notification
            _eventPublisher.EntityDeleted(ribbon);
        }

       
        /// <summary>
        /// Gets all Ribbons
        /// </summary>
        /// <param name="name">name</param>
        /// <param name="pageIndex">Page index</param>
        /// <param name="pageSize">Page size</param>
        /// <returns>Ribbons</returns>
        public virtual IPagedList<RibbonObject> GetAllRibbons(string text = "", int pageIndex = 0, int pageSize = int.MaxValue)
        {
            var query = _ribbonRepository.Table;
            if (!String.IsNullOrWhiteSpace(text))
                query = query.Where(s => s.Text.Contains(text));

            var ribbons = query.ToList();

            //paging
            return new PagedList<RibbonObject>(ribbons, pageIndex, pageSize);
        }

        /// <summary>
        /// Gets a ribbon
        /// </summary>
        /// <param name="ribbonId">ribbon identifier</param>
        /// <returns>ribbon</returns>
        public virtual RibbonObject GetRibbonById(int ribbonId)
        {
            if (ribbonId == 0)
                return null;

            string key = string.Format(CAROUSELS_BY_ID_KEY, ribbonId);
            return _cacheManager.Get(key, () => { return _ribbonRepository.GetById(ribbonId); });
        }

        /// <summary>
        /// Inserts a ribbon
        /// </summary>
        /// <param name="ribbon">Ribbon</param>
        public virtual void InsertRibbon(RibbonObject ribbon)
        {
            if (ribbon == null)
                throw new ArgumentNullException("ribbon");

            _ribbonRepository.Insert(ribbon);

            //event notification
            _eventPublisher.EntityInserted(ribbon);
        }

        /// <summary>
        /// Updates the ribbon
        /// </summary>
        /// <param name="ribbon">Ribbon</param>
        public virtual void UpdateRibbon(RibbonObject ribbon)
        {
            if (ribbon == null)
                throw new ArgumentNullException("ribbon");

            _ribbonRepository.Update(ribbon);

            //event notification
            _eventPublisher.EntityUpdated(ribbon);
        }

        #region Ribbon Entity

        /// <summary>
        /// Deletes a ribbon Entity
        /// </summary>
        /// <param name="ribbonProduct">Ribbon Entity</param>
        public virtual void DeleteRibbonProduct(RibbonProduct ribbonProduct)
        {
            if (ribbonProduct == null)
                throw new ArgumentNullException("ribbonProduct");

            _ribbonProductRepository.Delete(ribbonProduct);

            //event notification
            _eventPublisher.EntityDeleted(ribbonProduct);
        }

        /// <summary>
        /// Gets a ribbon Entities by ribbon identifier
        /// </summary>
        /// <param name="ribbonId">The ribbon identifier</param>
        /// <returns>Ribbon Entities</returns>
        public virtual IList<RibbonProduct> GetRibbonProductsByRibbonId(int ribbonId)
        {
            var query = from rp in _ribbonProductRepository.Table
                        where rp.RibbonId == ribbonId
                        select rp;
            var ribbonProducts = query.ToList();
            return ribbonProducts;
        }

        /// <summary>
        /// Gets a ribbon Entity
        /// </summary>
        /// <param name="ribbonProductId">Ribbon Entity identifier</param>
        /// <returns>Ribbon Entity</returns>
        public virtual RibbonProduct GetRibbonProductById(int ribbonProductId)
        {
            if (ribbonProductId == 0)
                return null;

            return _ribbonProductRepository.GetById(ribbonProductId);
        }

        /// <summary>
        /// Inserts a ribbon Entity
        /// </summary>
        /// <param name="ribbonProduct">Ribbon Entity</param>
        public virtual void InsertRibbonProduct(RibbonProduct ribbonProduct)
        {
            if (ribbonProduct == null)
                throw new ArgumentNullException("ribbonProduct");

            _ribbonProductRepository.Insert(ribbonProduct);

            //event notification
            _eventPublisher.EntityInserted(ribbonProduct);
        }

        /// <summary>
        /// Updates a ribbon Entity
        /// </summary>
        /// <param name="ribbonProduct">Ribbon Entity</param>
        public virtual void UpdateRibbonProduct(RibbonProduct ribbonProduct)
        {
            if (ribbonProduct == null)
                throw new ArgumentNullException("ribbonProduct");

            _ribbonProductRepository.Update(ribbonProduct);

            //event notification
            _eventPublisher.EntityUpdated(ribbonProduct);
        }

        /// <summary>
        /// Save entity
        /// </summary>
        /// <typeparam name="T">Type</typeparam>
        /// <param name="entity">Entity</param>
        public virtual void SaveRibbonProduct<T>(T product, int ribbonId) where T : BaseEntity
        {
            if (product == null)
                throw new ArgumentNullException("product");

            int productId = product.Id;
            string productName = typeof(T).Name;


            var query = from rp in _ribbonProductRepository.Table
                        where rp.ProductId == productId &&
                        rp.RibbonId == ribbonId
                        orderby rp.Id descending
                        select rp;
            var allRibbonProducts = query.ToList();
            var existingRibbonProduct = allRibbonProducts.FirstOrDefault();

            if (existingRibbonProduct == null)
            {
                //new record
                var ribbonProduct = new RibbonProduct()
                {
                    RibbonId = ribbonId,
                    ProductId = product.Id,
                    Published = true,
                };
                InsertRibbonProduct(ribbonProduct);
            }
            else
            {
                existingRibbonProduct.Published = true;
                UpdateRibbonProduct(existingRibbonProduct);
            }
        }

        #endregion

        #endregion


         }
}
